package com.wf.im.codec;

import com.wf.protobuf.domain.ProtoMsg;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * Protobuf解码
 *
 * @author wf
 * @since 2022/5/30
 */
@Slf4j
public class MyProtobufDecoder extends ByteToMessageDecoder {
    @Override
    public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 标记读取位置
        in.markReaderIndex();
        // 判断包头长度，小于两个字节说明一个short还没有读取完毕
        if (in.readableBytes() < 2) {
            return;
        }
        short len = in.readShort();
        if (len < 0) {
            // 长度小于0，非法数据，关闭连接
            ctx.close();
        }

        if (in.readableBytes() < len) {
            // 可读取字节小于预期消息长度，重置读取位置，下次重新读取
            in.resetReaderIndex();
        }
        byte[] arr;
//        in.readBytes(arr, 0, len);

        if (in.hasArray()) {
            // 堆缓冲
            ByteBuf slice = in.slice();
            arr = slice.array();
        } else {
            // 直接缓冲
            arr = new byte[len];
            in.readBytes(arr, 0, len);
        }

        ProtoMsg protoMsg = ProtoMsg.parseFrom(arr);
        if (protoMsg != null) {
            out.add(protoMsg);
        }
    }
}
